package com.hubao.flutter_weight_parser.protocol;



import com.hubao.flutter_weight_parser.protocol.exception.WeightProtocolClassNotFoundException;
import com.hubao.flutter_weight_parser.protocol.meta.JavaScriptWeightProtocolClass;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 分组的协议组
 */
public class ScopedWeightProtocols {
    private final Map<String, Map<String, WeightProtocol>> grouped = new HashMap<>();
    private final List<JavaScriptWeightProtocolClass> protocolClasses;

    private final Context context;
    private final Scriptable scriptable;

    public ScopedWeightProtocols(List<JavaScriptWeightProtocolClass> protocolClasses, Context context, Scriptable scriptable) {
        this.protocolClasses = protocolClasses;
        this.context = context;
        this.scriptable = scriptable;
    }

    /**
     * 创建一个分组
     *
     * @param name 分组名称
     */
    public void createScope(String name) {
        grouped.put(name, new HashMap<>());
    }

    /**
     * 销毁分组
     *
     * @param name 分组名称
     */
    public void removeScope(String name) {
        grouped.remove(name);
    }

    /**
     * 添加一个协议
     *
     * @param scope        分组
     * @param protocolName 协议名称
     */
    public void addProtocol(String scope, String protocolName, Context context) {
        grouped.get(scope).put(protocolName, getProtocolClass(protocolName).instance(context, scriptable));
    }

    /**
     * 移除协议
     * @param scope 分组
     * @param protocolName 协议名称
     */
    public void removeProtocol(String scope, String protocolName) {
        Map<String, WeightProtocol> protocolMap = grouped.get(scope);
        if (Objects.nonNull(protocolMap)) {
            protocolMap.remove(protocolName);
        }
    }

    /**
     * 获取指定协议
     * @param scope 分组
     * @param protocolName 协议名称
     */
    public WeightProtocol getProtocol(String scope, String protocolName) {
        if(!grouped.containsKey(scope)) {
            grouped.putIfAbsent(scope, new HashMap<>());
        }
        Map<String, WeightProtocol> protocolMap = grouped.get(scope);
        if(!protocolMap.containsKey(protocolName)) {
            protocolMap.putIfAbsent(protocolName, getProtocolClass(protocolName).instance(context, scriptable));
        }
        return protocolMap.get(protocolName);
    }

    private JavaScriptWeightProtocolClass getProtocolClass(String name) {
        return protocolClasses.stream().filter(clazz -> clazz.getClazzName().equals(name)).findAny().orElseThrow(() -> new WeightProtocolClassNotFoundException(name));
    }

    /**
     * 实例化一个支持分组的协议
     */
    public static ScopedWeightProtocols instance(final List<JavaScriptWeightProtocolClass> protocolClasses, Context context, Scriptable scriptable) {
        return new ScopedWeightProtocols(protocolClasses, context, scriptable);
    }

    public void destroy(){
        this.grouped.clear();
        this.protocolClasses.clear();
    }

}
